class Vue {
  constructor(obj_instance) {
    this.$data = obj_instance.data;
    // 初始化的时候调用数据监听函数
    Observer(this.$data);
    Compile(obj_instance.el,this)
  }
}
// 数据劫持 - 监听实例里数据
function Observer(data_instance) {
  if (!data_instance || typeof data_instance !== "object") return;
  const dependency = new Dependency()
  // Object.keys可以返回一个数组，返回对象里的每一个属性
  // console.log(Object.keys(data_instance))
  // 将数组中的每一项遍历并监听       使用Object.defineProperty(操作对象，操作属性，{})
  Object.keys(data_instance).forEach((key) => {
    let value = data_instance[key];
    Observer(value);
    Object.defineProperty(data_instance, key, {
      enumerable: true, // 可枚举的
      configurable: true, // 可删除的
      // writable:true, //可编辑的
      get() {
        console.log(`访问了属性：${key} -> 值：${value}`);
        // console.log(Dependency.temp)
        // 订阅者加入依赖实例的数组
        Dependency.temp&& dependency.addSub(Dependency.temp)
        if(Dependency.temp){
          console.log(Dependency.temp)
        }
        return value;
      },
      set(newValue) {
        console.log(`属性${key}的值${value}被修改为${newValue}`);
        value = newValue;
        Observer(newValue);
        dependency.notify()
      },
    });
  });
}

// HTML模板解析 ——替换dom 第一个参数是真实DOM元素  第二个元素是vm实例
function Compile(element, vm) {
  vm.$el = document.querySelector(element);
  // 创建文档碎片
  const fragment = document.createDocumentFragment();
  let child;
  while ((child = vm.$el.firstChild)) {
    fragment.append(child);
  }
  console.log(fragment);
  console.log(fragment.childNodes);
  // 替换文档碎片内容
  fragment_compile(fragment);
  function fragment_compile(node) {
    const pattern = /\{\{\s*(\S+)\s*\}\}/;
    if (node.nodeType === 3) {
      const xxx=node.nodeValue
      const result_regex = pattern.exec(node.nodeValue);
      if (result_regex) {
        const arr = result_regex[1].split(".");
        const value = arr.reduce(
          (total, current) => total[current], vm.$data
        );
        node.nodeValue = xxx.replace(pattern, value);
          // 创建订阅者
          new Watcher(vm,result_regex[1],newValue=>{
            node.nodeValue=xxx.replace(pattern,newValue);
          })
      }
      console.log(node);
      console.log(node.nodeValue);
      return;
    }
    if(node.nodeType===1 && node.nodeName==="INPUT"){
      const attr =Array.from(node.attributes)
      attr.forEach(i=>{
        if(i.nodeName==="v-model"){
          const value = i.nodeValue.split('.').reduce(
            (total,current)=>total[current],vm.$data
          )
          node.value=value
          new Watcher(vm,i.nodeValue,newValue=>{
            node.value=newValue
          })
          node.addEventListener('input',e=>{
            // const name = i.nodeValue
            // console.log(name)
            // vm.$data[name]=e.target.value
            const arr1 = i.nodeValue.split('.')
            console.log(arr1)
            const arr2 = arr1.slice(0,arr1.length-1)
            console.log(arr2)
            const final = arr2.reduce(
              (total,current)=>total[current],vm.$data
            )
            final[arr1[arr1.length-1]]=e.target.value
          })
        }
      })
    }
    node.childNodes.forEach((child) => fragment_compile(child));
  }
  vm.$el.appendChild(fragment)
}

// 依赖  -收集订阅者和通知者
class Dependency {
  constructor(){
    // 存放订阅者的列表
    this.subscribers=[]
  }
  addSub(sub){
    this.subscribers.push(sub)
  }
  // 通知订阅者遍历数组的方法 让订阅者的调用update来更新
  notify(){
    this.subscribers.forEach(sub=>sub.update())
  }
}

// 订阅者类
class Watcher{
  constructor(vm,key,callback){
    this.vm=vm;
    this.key=key
    // 该回调函数记录如何跟新文本内容
    this.callback=callback
    Dependency.temp=this
    console.log(`用属性${key}创建了订阅者`)
    key.split('.').reduce((total,current)=>total[current],vm.$data)
    Dependency.temp=null
  }
  update(){
    const value = this.key.split('.').reduce
    ((total,current)=>total[current],this.vm.$data)
    this.callback(value)
  }
}